﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Forms;
using System.Threading;
using System.Configuration;

namespace LineWatch_WinForm
{
    public delegate void InterfaceUpdateHandler(string text, string portName);

    public class SerialPortOperator : Control
    {
        private SerialPort Sp = new SerialPort();

        public InterfaceUpdateHandler InterfaceUpdateHandle;

        public SerialPortOperator()
        {

        }

        public SerialPortOperator(string portName, int baudRate)
        {
            this.InitPort(portName, baudRate);
        }

        /// <summary>
        /// Sp Data Received
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Sp_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            string t = ConfigurationManager.AppSettings["ThreadSleepTime"];
            int outT;
            if (!int.TryParse(t, out outT)) outT = 200;
            Thread.Sleep(outT);
            Sp.DataReceived -= new SerialDataReceivedEventHandler(Sp_DataReceived);

            byte[] readBuffer = new byte[Sp.ReadBufferSize];
            if (!Sp.IsOpen) return;
            Sp.Read(readBuffer, 0, readBuffer.Length);

            // 不停顿连续扫描会有问题

            string sn = Encoding.ASCII.GetString(readBuffer);

            int index = sn.IndexOf("@");
            if (index == -1) return;
            sn = sn.Substring(index + 5, sn.Length - index - 5);//remove @00rd
            if (sn[0] != '0' || sn[1] != '0') return;
            sn = sn.Substring(2, sn.Length - 2);

            // 扫描出来的数据回事这样的：31012341001G\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0...
            index = sn.IndexOf("\0");
            sn = sn.Substring(0, index);

            sn = sn.Replace("\n", string.Empty);
            sn = sn.Replace("\r", string.Empty);
            sn = sn.Replace("*", string.Empty);
            string checkNum = sn.Substring(sn.Length - 2, 2);

            sn = sn.Substring(0, sn.Length - 2);

            if (GetFCSD("@00RD" + sn) != checkNum) return;

            if (InterfaceUpdateHandle != null)
            {
                this.Invoke(InterfaceUpdateHandle,
                            new string[] { sn, Sp.PortName });
            }

            Sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);
        }

        /// <summary>
        /// Init Port
        /// </summary>
        /// <param name="portName"></param>
        /// <param name="baudRate"></param>
        public void InitPort(string portName, int baudRate)
        {
            Sp.PortName = portName;
            Sp.BaudRate = baudRate;
            Sp.Parity = Parity.Even;
            Sp.StopBits = StopBits.Two;
            Sp.DataBits = 7;
            Sp.DataReceived += new SerialDataReceivedEventHandler(Sp_DataReceived);
            Sp.ReceivedBytesThreshold = 1;
            try
            {
                Sp.Open();
            }
            catch (Exception ex)
            {
                MessageBox.Show("端口" + portName + "打开失败！");
                throw ex;
            }
        }

        /// <summary>
        /// Write Line
        /// </summary>
        /// <param name="text"></param>
        public void WriteLine(string text)
        {
            if (Sp.IsOpen)
            {
                string fcsd = GetFCSD(text);

                text += (fcsd + "*" + (char)13);

                Sp.WriteLine(text);
            }
        }

        private string GetFCSD(string text)
        {
            string FCSD = string.Empty;
            int Q = 0;
            for (int i = 0; i < text.Length; i++) Q = Convert.ToChar(text.Substring(i, 1)) ^ Q;
            FCSD = String.Format("{0:X}", Q);
            FCSD = FCSD.PadLeft(2, '0');
            return FCSD;
        }

        /// <summary>
        /// Close Port
        /// </summary>
        public void ClosePort()
        {
            Sp.Close();
        }
    }
}
